#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
医学图像处理作业
包括：
1. 图像质量评价（基于直方图）
2. 直方图绘制
3. 图像增强（直方图均衡化）
4. 图像分割（基于阈值方法）
5. 图像压缩
"""

# 添加用户Python路径以确保能找到cv2模块
import sys
import os
user_site_packages = os.path.join(os.path.expanduser("~"), "AppData", "Roaming", "Python", "Python312", "site-packages")
if os.path.exists(user_site_packages) and user_site_packages not in sys.path:
    sys.path.append(user_site_packages)

try:
    import cv2
except ImportError:
    print("无法导入cv2模块，请确保已正确安装OpenCV库")
    print("可以使用以下命令安装: pip install --user opencv-python")
    sys.exit(1)

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from PIL import Image
import os

# 设置中文字体
font = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf", size=12)

def load_image(image_path):
    """
    加载图像
    
    参数:
        image_path: 图像路径
    返回:
        原始图像和灰度图像
    """
    # 读取图像
    image = cv2.imread(image_path)
    if image is None:
        raise ValueError(f"无法读取图像: {image_path}")
    
    # 转换为RGB（OpenCV默认是BGR）
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # 转换为灰度图
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    return image_rgb, gray_image

def plot_histogram(image, title="图像直方图", save_path=None):
    """
    绘制并显示图像直方图
    
    参数:
        image: 输入图像（灰度图）
        title: 直方图标题
        save_path: 保存路径，如果为None则不保存
    """
    plt.figure(figsize=(10, 6))
    
    # 计算直方图
    hist = cv2.calcHist([image], [0], None, [256], [0, 256])
    
    # 绘制直方图
    plt.plot(hist, color='black')
    plt.xlim([0, 256])
    plt.title(title, fontproperties=font)
    plt.xlabel('像素强度', fontproperties=font)
    plt.ylabel('像素数量', fontproperties=font)
    plt.grid(True)
    
    if save_path:
        plt.savefig(save_path)
    
    plt.show()

def evaluate_image_quality(image):
    """
    评价图像质量（基于直方图分析）
    
    参数:
        image: 灰度图像
    返回:
        质量评价结果（字典）
    """
    # 计算直方图
    hist = cv2.calcHist([image], [0], None, [256], [0, 256])
    hist = hist.flatten() / hist.sum()  # 归一化直方图
    
    # 计算图像质量指标
    # 1. 平均灰度值
    mean_value = np.mean(image)
    
    # 2. 标准差（对比度指标）
    std_dev = np.std(image)
    
    # 3. 熵（信息量）
    epsilon = 1e-10  # 避免log(0)
    entropy = -np.sum(hist * np.log2(hist + epsilon))
    
    # 4. 动态范围
    dynamic_range = np.max(image) - np.min(image)
    
    # 5. 直方图均匀性（理想情况下直方图应该均匀分布）
    uniformity = np.sum(np.square(hist))
    
    return {
        "平均灰度值": mean_value,
        "标准差（对比度）": std_dev,
        "熵（信息量）": entropy,
        "动态范围": dynamic_range,
        "直方图均匀性": uniformity
    }

def enhance_image(image):
    """
    图像增强（直方图均衡化）
    
    参数:
        image: 灰度图像
    返回:
        增强后的图像
    """
    # 应用直方图均衡化
    enhanced_image = cv2.equalizeHist(image)
    return enhanced_image

def segment_image(image, threshold_value=127):
    """
    图像分割（基于阈值方法）
    
    参数:
        image: 灰度图像
        threshold_value: 阈值（默认127）
    返回:
        分割后的二值图像
    """
    # 应用阈值分割
    _, segmented_image = cv2.threshold(image, threshold_value, 255, cv2.THRESH_BINARY)
    return segmented_image

def compress_image(image_path, output_path, quality=85):
    """
    图像压缩
    
    参数:
        image_path: 原始图像路径
        output_path: 压缩后图像保存路径
        quality: 压缩质量（1-100），默认85
    返回:
        压缩前后的文件大小（字节）
    """
    # 使用PIL进行图像压缩
    img = Image.open(image_path)
    img.save(output_path, quality=quality, optimize=True)
    
    # 获取压缩前后的文件大小
    original_size = os.path.getsize(image_path)
    compressed_size = os.path.getsize(output_path)
    
    return original_size, compressed_size

def display_images(images, titles, figsize=(15, 10)):
    """
    显示多个图像
    
    参数:
        images: 图像列表
        titles: 标题列表
        figsize: 图像大小
    """
    n = len(images)
    plt.figure(figsize=figsize)
    
    for i in range(n):
        plt.subplot(1, n, i+1)
        if len(images[i].shape) == 2:  # 灰度图
            plt.imshow(images[i], cmap='gray')
        else:  # 彩色图
            plt.imshow(images[i])
        plt.title(titles[i], fontproperties=font)
        plt.axis('off')
    
    plt.tight_layout()
    plt.show()

def main():
    # 图像路径
    image_path = r"H:\vscode\python\something-1\IMG_0634.JPG"
    
    # 输出目录
    output_dir = r"H:\vscode\python\something-1\output"
    os.makedirs(output_dir, exist_ok=True)
    
    # 1. 加载图像
    print("正在加载图像...")
    original_image, gray_image = load_image(image_path)
    
    # 2. 显示原始图像
    display_images([original_image, gray_image], ["原始图像", "灰度图像"])
    
    # 3. 绘制直方图
    print("正在绘制直方图...")
    plot_histogram(gray_image, "灰度图像直方图", os.path.join(output_dir, "histogram.png"))
    
    # 4. 评价图像质量
    print("正在评价图像质量...")
    quality_metrics = evaluate_image_quality(gray_image)
    for metric, value in quality_metrics.items():
        print(f"{metric}: {value:.4f}")
    
    # 5. 图像增强（直方图均衡化）
    print("正在进行图像增强...")
    enhanced_image = enhance_image(gray_image)
    plot_histogram(enhanced_image, "增强后图像直方图", os.path.join(output_dir, "enhanced_histogram.png"))
    
    # 显示增强前后的对比
    display_images([gray_image, enhanced_image], ["原始灰度图像", "直方图均衡化后"])
    
    # 6. 图像分割（阈值法）
    print("正在进行图像分割...")
    # 使用Otsu自动阈值
    otsu_threshold, segmented_image_otsu = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    print(f"Otsu自动阈值: {otsu_threshold}")
    
    # 使用固定阈值
    segmented_image_fixed = segment_image(gray_image, 127)
    
    # 显示分割结果
    display_images([gray_image, segmented_image_otsu, segmented_image_fixed], 
                  ["原始灰度图像", f"Otsu阈值分割 (阈值={otsu_threshold:.1f})", "固定阈值分割 (阈值=127)"])
    
    # 7. 图像压缩
    print("正在进行图像压缩...")
    compressed_path = os.path.join(output_dir, "compressed.jpg")
    original_size, compressed_size = compress_image(image_path, compressed_path, quality=75)
    
    compression_ratio = original_size / compressed_size
    print(f"原始图像大小: {original_size / 1024:.2f} KB")
    print(f"压缩后图像大小: {compressed_size / 1024:.2f} KB")
    print(f"压缩比: {compression_ratio:.2f}")
    
    # 保存处理后的图像
    cv2.imwrite(os.path.join(output_dir, "enhanced.jpg"), enhanced_image)
    cv2.imwrite(os.path.join(output_dir, "segmented_otsu.jpg"), segmented_image_otsu)
    cv2.imwrite(os.path.join(output_dir, "segmented_fixed.jpg"), segmented_image_fixed)
    
    print("处理完成！所有结果已保存到输出目录。")

if __name__ == "__main__":
    main()
